<?php if(!defined('OCTOMS')){header('HTTP/1.1 403');die('{"error":"forbidden"}');}
/*
 * @package       Fervoare.com
 * @link          http://Fervoare.com
 * @copyright     Copyright 2011, Valentino-Jivko Radosavlevici (http://valentino.radosavlevici.com)
 * @license       GPL v3.0 (http://www.gnu.org/licenses/gpl-3.0.txt)
 * 
 * Redistributions of files must retain the above copyright notice.
 * 
 * @since         Fervoare.com 0.0.1
 */
	
	/*
	 * Authentication library
	 * 
	 * @package Fervoare.com
	 * @version 0.1
	 * 
	 * @author Valentino-Jivko Radosavlevici
	 */
	class auth_l
	{
		/*
		 * User information
		 * @var mixed
		 */
		var $user = false;
		
		/*
		 * Available roles; the 'admin' key is mandatory
		 * @var array
		 */
		var $roles = array('admin'=>1,'user'=>2,'guest'=>3);
		
		/*
		 * Active time interval; in seconds
		 * 2 minutes
		 */
		var $active_time = 120;
		
		/*
		 * Constructor
		 * 
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function __construct()
		{
			// Load the session
			$this->session = octoms('session');
			if (!$this->session->is_started())
			{
				$this->session->start();
			}
			
			// Load the sql engine
			$this->sql = octoms('sql');
			
			// Always refresh the user information
			$this->refresh();
						
		}// end function __construct()
		
		/**
		 * Set the log out flag
		 * 
		 * @example 
		 * // Mark the user for log out
		 * {auth}->flag_log_out();
		 * // Unmark the user
		 * {auth}->flag_log_out(false);
		 * 
		 * @param bool $val - Wether to set the flag on or off
		 * @param int $id - User id to mark
		 * @return bool - True on success, False on failure
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function flag_log_out($val=true,$id=null)
		{
			try
			{
				// Get the id
				if (is_null($id))
				{
					$id = (isset($this->user['id']))?$this->user['id']:0;
				}
				
				// The user is not logged in, but there is a "log_out_flag" set
				$this->sql->query(
					$this->sql->_update(
						'users',
						array(
							'log_out_flag'=>$val?1:0
						),
						$this->sql->_where(
							array(
								'id'=>$id
							)
						)
					)
				);
				
				// All done
				return true;
			}
			catch(Exception $e)
			{
				return false;
			}
			
		}// end function flag_log_out()
		
		/**
		 * Is the user logged in?
		 * 
		 * @example 
		 * // Verify the user is logged in
		 * {auth}->is_logged()?'':'';
		 * 
		 * @return boolean - True if the user is logged in, False otherwise
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function is_logged()
		{
			// Get the user first
			$this->user();
			
			// Return the result
			return !empty($this->user);
			
		}// end function is_logged()
		
		/**
		 * Log In
		 * 
		 * @example
		 * // Log the user in
		 * {auth}->log_in('foo','bar'); 
		 * 
		 * @param string $user
		 * @param string $password
		 * @return boolean - True on success, False on error
		 * @throws Exception
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function log_in($user,$password)
		{
			if (FALSE !== ($id = $this->verify($user, $password)))
			{
				// Remove the flag
				$this->flag_log_out(false,$id);
				
				// Refresh the user id
				return $this->refresh($id);
			}
			else
			{
				// The user id is invalid
				return false;
			}
			
		}// end function log_in()
		
		/**
		 * Log Out
		 * 
		 * @example 
		 * // Log out
		 * {auth}->log_out();
		 * 
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function log_out()
		{
			// Reset the session information
			$this->session->reset('user');
			
			// Clear the local variable
			$this->user = false;
			
		}// end function log_out()
		
		/**
		 * Mark the user as active
		 * 
		 * @example 
		 * // Mark the current user as active
		 * {auth}->mark_active();
		 * 
		 * @param string $user
		 * @return boolean - True on success, false on failure
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function mark_active()
		{
			// If the user is not logged, stop
			if (!$this->is_logged())
			{
				return false;
			}
			
			// Get the last active information
			$last_active = (isset($this->user['last_active']))?intval($this->user['last_active']):0;
			
			// Set the user id or username
			$user = $this->user['id'];

			// Update in order?
			if ( (time()-$last_active) >= $this->active_time)
			{
				try 
				{
					// Execute the query
					$this->sql->query(
						$this->sql->_update(
							'users',
							array(
								'last_active'=>time(),
								'last_active_page'=>(lang().'::'.implode(WS, octoms::$oms_url_segments)),
								'last_ip'=>$_SERVER['REMOTE_ADDR']
							),
							$this->sql->_where(
								array(
									'id' => $user
								)
							)
						)
					);

					// All went well
					return true;
				}
				catch (Exception $e)
				{
					flag($e->getMessage());
					return false;					
				}
			}
			else 
			{
				return true;
			}
			
		}// end function mark_active()
		
		/**
		 * Refresh user information
		 * 
		 * @example 
		 * // Refresh the user information
		 * {auth}->refresh();
		 * // Used to log in; provide the ID to load
		 * {auth}->refresh(10);
		 * // If the user is already logged (ex. user #1), $id will be ignored
		 * {auth}->refresh(10); # will refresh the info for id 1
		 * 
		 * @return boolean - True on success, False on failure
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function refresh($id=null)
		{
			// Get the user already logged in
			if(!is_null($u = $this->session->get('user')))
			{
				$id = $u['id'];
			}
			else 
			{
				// No id provided?
				if (is_null($id))
				{
					// Log out
					$this->log_out();
					
					// Bad id
					return false;
				}
			}
			
			try 
			{
				// Get user information
				$user = $this->sql->query(
					$this->sql->_select(
						null,
						'users',
						$this->sql->_where(
							array(
								'id'=>$id
							)
						)
					)
				);
				
				// Any results?
				if ($user->num_rows()>0)
				{
					// Get the first result
					$user = $user->first();
					
					// Never keep the password
					unset($user['password']);
					
					// Forced log out?
					if ($user['log_out_flag'])
					{
						// Log out
						$this->log_out();
												
						// All done
						return false;
					}
					else 
					{
						// Save info to session
						$this->session->set('user',$user);
						
						// Save it to the local variable
						$this->user = $user;
						
						// That was it
						return true;
					}
				}
				else 
				{
					// Log out
					$this->log_out();
					
					// Bad user refresh
					return false;
				}
				
			}
			catch (Exception $e)
			{
				// Save this for debugging purposes
				flag($e->getMessage());
				return false;
			}
			
		}// end function refresh()
		
		/**
		 * Register a new user
		 * 
		 * @param string $username
		 * @param string $password
		 * @return boolean - True on success, False on error
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function register($username='',$password='')
		{
			try 
			{
				// Insert query
				$this->sql
					->query(
						$this->sql->_insert(
							'users',
							array(
								'username'=>$username,
								'password'=>md5($password)
							)
						)
					);
			
				// All went well?
				return (false !== $this->sql->result());
			}
			catch (Exception $e)
			{
				// Flag this in case we need it
				flag($e->getMessag());
				
				// Bad result
				return false;
			}
		}// end function register()
		
		/**
		 * User role.
		 * This is also important for method permissions set with the 'allow' tag in their comment section.
		 * There are 3 groups (in descending order by their priority):<ul>
		 * <li>admin - [default] the highest priority, access to all methods</li>
		 * <li>user - lesser than the admin</li>
		 * <li>guest - lesser than the user</li>
		 * </ul>
		 * Ex.: setting '[at]allow user' in the comment section of a method makes it available for the 'user' group and the 'admin' group only;
		 * 
		 * @example 
		 * // Get the user role
		 * {auth}->role();
		 * 
		 * @return string/bool - String, user role or False on error
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function role()
		{
			// Return the role
			return isset($this->user['role'])?intval($this->user['role']):false;
			
		}// end function role()
		
		/**
		 * Get the role name
		 * 
		 * @example 
		 * // Get the user's role name
		 * {auth}->role_name();
		 * 
		 * @return string/bool - String, role name OR False on failure
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function role_name()
		{
			if (false !== $role = $this->role())
			{
				return array_search(intval($role), $this->roles);
			}
			else 
			{
				return false;
			}
			
		}// end function role_name()
		
		/**
		 * User information
		 * 
		 * @param boolean $asObject - True if the result should be an Object, false for an Array
		 * @return array/null - Array user information or NULL if the user is not set
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function user($asObject=false)
		{
			// Populate the user property
			$this->user = $this->session->get('user');
			
			// Return the information
			if (!is_null($this->user))
			{
				return $asObject?array_to_object($this->user):$this->user;
			}
			else 
			{
				return null;
			}
			
		}// end function user()
		
		/**
		 * Verify user login credentials
		 * 
		 * @example 
		 * // Verify user credentials for username 'x'
		 * {auth}->verify('x','password');
		 * // Verify user credentials for user with id 1
		 * {auth}->verify(1,'password',true);
		 * 
		 * @param string/int $user
		 * @param string $password
		 * @param bool $useId - wether $user is an ID or a username
		 * @return string/bool - user ID or FALSE on failure
		 * @package Fervoare.com
		 * 
		 * @author Valentino-Jivko Radosavlevici
		 */
		function verify($user=false,$password=false,$useId=false)
		{
			// Prepare the query array
			$select[$useId?'id':'username'] = $user;
			$select['password'] = md5($password);
			
			// Check the credentials
			$this->sql->query(
				$this->sql->_select(
					null,
					'users',
					$this->sql->_where(
						$select
					)
				)
			);
			
			// Return the user id
			if ($this->sql->num_rows()>0)
			{
				$user = $this->sql->first();
				return $user['id'];
			}
			else
			{
				return false;
			}
			
		}// end function verify()
		
	}// end class auth_l
	
	
/* End Of File <auth.inc> */